/** 导出excel */
import request from '@/utils/request'
import { ccDict, getDictByType } from '@/api/dataDict'
import { downFileByA, pageRequsetBody } from '@/utils'
export async function exportExcelFile({ url, bodyData, dataSource, filename, method, fields, tableConfig, exclude, sepCol, sepRow, timeout } = {}) {
  tableConfig ? '' : tableConfig = { setting: [] }
  if (!fields) {
    fields = {}
  }
  await toFields(tableConfig, fields, exclude || []).then(r => {
    fields = r
  })
  if (dataSource) {
    return new Promise((resolve, reject) => {
      dataToExcel(dataSource, fields, filename)
      return resolve()
    })
  }
  return request({
    method,
    url: url || tableConfig.interfacePath,
    timeout: timeout || 10 * 60 * 1000, // 默认10分钟
    data: pageRequsetBody({
      order: 'desc',
      pageFlag: true,
      page: 1,
      rows: 50000, // 最多导出5万条数据
      ...bodyData
    })
  }).then(async res => {
    const records = res.data.records
    dataToExcel(records, fields, filename)
  })
}
// tablebox转换fields
export async function toFields(tableConfig, fieldsRaw, exclude = []) {
  const fields = {}
  for (const key of Object.keys(fieldsRaw)) {
    if (exclude.includes(key)) {
      continue
    }
    fields[key] = {}
    const field = fields[key]
    const fieldRaw = fieldsRaw[key]
    // 判断是字符串还是对象
    if (typeof fieldRaw === 'string') {
      field.label = fieldRaw
      continue
    }
    field.label = fieldRaw.label
    if (fieldRaw.formatData) {
      field.formatData = fieldRaw.formatData
    }
    let handler
    if (fieldRaw.propEnum) {
      await handlePropEnum(fieldRaw.propEnum).then(dict => {
        handler = getDictName(dict)
      })
    }
    if (handler) {
      field.handler = handler
    }
  }

  const tableFields = {}
  // 合并fieldsRaw 和 setting
  for (const item of tableConfig.setting) {
    if ((item.prop || item.formatData) && !exclude.includes(item.prop)) {
      const { formatData, propEnum, label } = item
      if (label === '序号') {
        continue
      }
      let handler
      if (propEnum) {
        await handlePropEnum(propEnum).then(dict => {
          handler = getDictName(dict)
        })
      }
      const field = {
        label,
        formatData,
        handler
      }
      if (item.prop) {
        tableFields[item.prop] = Object.assign(field, tableFields[item.prop] || {})
      } else {
        tableFields[Math.floor(Math.random() * 0xffffffffffff).toString(16)] = field
      }
    }
  }
  // 合并
  for (const [k, v] of Object.entries(fields)) {
    const vv = tableFields[k]
    if (vv) {
      tableFields[k] = Object.assign(vv, v)
    } else {
      tableFields[k] = v
    }
  }
  return tableFields
}
// 处理数据字典
export async function handlePropEnum(propEnum) {
  if (!propEnum) {
    return undefined
  }
  let dict = []
  if (propEnum.appCode) {
    await getDictByType(propEnum).then(res => {
      dict = res.data
    })
  } else {
    await ccDict(propEnum.dictTypeCode).then(res => {
      dict = res.data
    })
  }
  return dict
}
function getDictName(dict, v) {
  return v => {
    if (v === undefined || v === null) {
      return ''
    }
    const values = v.toString().split(',')
    const result = []
    for (const code of values) {
      for (const item of dict) {
        if (item.dictCode === code) {
          result.push(item.dictName)
        }
      }
    }
    if (result.length > 0) {
      return result.join(',')
    }
    return v
  }
}

export async function dataToExcel(records, fields, filename) {
  return new Promise((reslove, reject) => {
    const t = [Object.values(fields).map(e => e.label)]
    const fieldsKeys = Object.keys(fields)
    for (const r of records) {
      const row = []
      for (const field of fieldsKeys) {
        let d = r[field]
        const f = fields[field]
        if (f.formatData instanceof Function) {
          d = f.formatData(r)
        } else if (f.handler instanceof Function) {
          d = f.handler(d)
        }
        if (d !== undefined && d !== null && typeof d !== 'object') {
          row.push(d)
        } else if (typeof d === 'object') {
          if (d instanceof Array) {
            d = d.join(',')
          } else if (Object.prototype.toString.call(d, '[object Object]')) {
            d = Object.values(d).join(',')
          }
          row.push(d)
        } else {
          row.push('')
        }
      }
      t.push(row)
    }
    const b = window.createExcel(filename, '导出', JSON.stringify(t))
    const f = URL.createObjectURL(new Blob([b]))
    downFileByA(f, filename)
    setTimeout(() => {
      URL.revokeObjectURLf
      reslove('')
    }, 1000 * 3)
  })
}
